package cn.qmso.wxPay.v3;

import cn.qmso.wxPay.v3.base.Pay;
import cn.qmso.wxPay.v3.base.WxPayV3Content;
import cn.qmso.wxPay.v3.base.WxPlatformCert;
import cn.qmso.wxPay.v3.config.WxPayV3Config;
import cn.qmso.wxPay.v3.paramEntity.transfer.TransferParam;
import cn.qmso.wxPay.v3.paramEntity.transfer.TransferParamDetail;
import cn.qmso.wxPay.v3.paramEntity.only.vo.transfer.TransferVo;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import cn.qmso.wxPay.v3.paramEntity.transfer.BatchesParam;
import cn.qmso.wxPay.v3.paramEntity.only.vo.transfer.batches.BatchesVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.IllegalBlockSizeException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.CertificateException;

/**
 * @author : ljt
 * @version V1.0
 * @Description: 微信商家转账接口
 * @date Date : 2022年07月26日 15:28
 */
@Slf4j
@Component
public class WxTransferV3 extends Pay {

    @Autowired
    private WxPayV3Config defaultWxPayV3Config;


    /**
     * 查询商家转账到零钱结果
     * @param batchesParam 查询参数
     * @param batchId 微信批次单号
     * @return 查询结果
     */
    public BatchesVo selectTransfer(BatchesParam batchesParam, String batchId)
            throws URISyntaxException, NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException, IllegalAccessException {
        return selectTransfer(batchesParam,batchId,defaultWxPayV3Config);
    }

    /**
     * 查询商家转账到零钱结果
     * @param batchesParam 查询参数
     * @param batchId 微信批次单号
     * @param wxPayV3Config 配置信息
     * @return 查询结果
     */
    public BatchesVo selectTransfer(BatchesParam batchesParam, String batchId, WxPayV3Config wxPayV3Config)
            throws URISyntaxException, NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException, IllegalAccessException {
        Object body = getRequest(WxPayV3Content.URL_PRE + String.format(WxPayV3Content.V3_TRANSFER_SELECT,batchId),
                batchesParam,
                wxPayV3Config);
            ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(body.toString(), new TypeReference<BatchesVo>() {});
    }

    /**
     * 发起商家转账到零钱
     * @param transferParam 转账信息
     * @return 转账信息
     * @throws Exception 异常
     */
    public TransferVo transfer(TransferParam transferParam) throws Exception {
        return transfer(transferParam,defaultWxPayV3Config);
    }

    /**
     * 发起商家转账到零钱
     * @param transferParam 转账信息
     * @param wxPayV3Config 配置信息
     * @return 转账信息
     */
    public TransferVo transfer(TransferParam transferParam, WxPayV3Config wxPayV3Config)
            throws CertificateException, NoSuchAlgorithmException, IOException, SignatureException, InvalidKeyException, IllegalBlockSizeException {
        WxPlatformCert certificateByV3Key = getCertificateByV3Key(wxPayV3Config.getKey());
        for (TransferParamDetail transferDetailBo : transferParam.getTransfer_detail_list()) {
            if (StringUtils.isNotEmpty(transferDetailBo.getUser_name())){
                String encrypt = rsaEncryptOAEP(transferDetailBo.getUser_name(), certificateByV3Key.getCertificate().getPublicKey());
                transferDetailBo.setUser_name(encrypt);
            }
        }
        String body = postRequest(WxPayV3Content.URL_PRE + WxPayV3Content.V3_TRANSFER_BATCHES,
                certificateByV3Key.getSerialNo(),
                JSONObject.toJSONString(transferParam),
                wxPayV3Config);
        TransferVo transferVo = null;
        try {
            ObjectMapper mapper = new ObjectMapper();
            transferVo = mapper.readValue(body,
                    new TypeReference<TransferVo>() {
                    });
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return transferVo;
    }


}
